﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using CuttingEdge.Conditions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using PSAMMatrixCloud.Common;
using PSAMMatrixCloud.Common.HttpParameterCommon;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using PSAMMatrixCloud.Model.Base;
using PSAMMatrixCloud.BLL.WebAPI;
using Newtonsoft.Json.Converters;

namespace PSAMMatrixCloud.WebAPI
{
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class WebAPIWork
    {
        private readonly RequestDelegate _next;
        private static  IServiceProvider ServiceProvider;

        public WebAPIWork(RequestDelegate next) 
        {
            _next = next;
        }



        public Task Invoke(HttpContext context) 
        {
            //所有入参小写，入参实体类也小写
            //所有出参小写，出餐实体类也小写
            //入参实体类命名在相应的Model 后面加ex ；如果 一个modelex不够用则在同一个文件下面加另外的类
            //Dal层新增文件 后面加ex，类名与生成器生成的类名一致
            //业务层新增文件后面加ex，类名与生成器生成的类名一致
            SimpleResult ret = new SimpleResult(); //反馈结果类
            bool isContinue = true;
            context.Response.ContentType = "text/plain;charset=utf-8";
            IDictionary<object, object> items = context.Items;


            SortedDictionary<string, string> sPara = HttpParameterCore.GetRequestPost(context);
            Dictionary<string, object> _inParams = new Dictionary<string, object>();//日志记录
            Stopwatch stopwatch = Stopwatch.StartNew();//启动计时器
            
            //定参
            string appID = (sPara.ContainsKey("AppID".ToLower())) == true ? sPara["AppID".ToLower()].ToString().Trim() : "";//应用ID
            string userID = (sPara.ContainsKey("UserID".ToLower())) == true ? sPara["UserID".ToLower()].ToString().Trim() : "";//用户id
            string methodName = (sPara.ContainsKey("MethodName".ToLower()) == true) ? sPara["MethodName".ToLower()].ToString().Trim() : "";//调用接口名
            string version = (sPara.ContainsKey("Version".ToLower()) == true) ? sPara["Version".ToLower()].ToString().Trim() : "";//接口版本号
            string timestamp = (sPara.ContainsKey("Timestamp".ToLower())) == true ? sPara["Timestamp".ToLower()].ToString().Trim() : "";//时间戳
            string sign = (sPara.ContainsKey("Sign".ToLower())) == true ? sPara["Sign".ToLower()].ToString().Trim() : "";

            //需参
            string postData = (sPara.ContainsKey("PostData".ToLower())) == true ? sPara["PostData".ToLower()].ToString().Trim() : ""; //外部提交上的参数

            try
            {
                //基础定参验证
                Condition.Requires(appID, "appID").IsNotNullOrWhiteSpace();//appID不能为空或者空字符串
                Condition.Requires(methodName, "methodName").IsNotNullOrWhiteSpace();//methodName不能为空或者空字符串
                Condition.Requires(version, "version").IsNotNullOrWhiteSpace();//version不能为空或者空字符串
                Condition.Requires(timestamp, "timestamp").IsNotNullOrWhiteSpace();//timestamp不能为空或者空字符串
                Condition.Requires(sign, "sign").IsNotNullOrWhiteSpace();//sign不能为空或者空字符串


                if (isContinue)
                {
                    switch (methodName.Trim().ToLower())
                    {
                        case "psamcloud.boss.device.lane.add":
                            ret = new LaneDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Add(appID, userID, postData);
                            break;
                        case "psamcloud.boss.device.lane.update":
                            ret = new LaneDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Edit(appID, userID, postData);
                            break;
                        case "psamcloud.boss.device.lane.delete":
                            ret = new LaneDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Del(appID, userID, postData);
                            break;
                        case "psamcloud.boss.device.lane.list":
                            ret = new LaneDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Search(appID, userID, postData);
                            break;
                        case "psamcloud.boss.device.lane.sendmail"://发送邮件
                            ret = new LaneDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Email(appID, userID, postData);
                            break;
                        case "psamcloud.boss.device.psam.add":
                            ret = new PSAMDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Add(appID, userID, postData);
                            break;
                        case "psamcloud.boss.device.psam.update":
                            ret = new PSAMDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Edit(appID, userID, postData);
                            break;
                        case "psamcloud.boss.device.psam.delete":
                            ret = new PSAMDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Del(appID, userID, postData);
                            break;
                        case "psamcloud.boss.device.psam.list":
                            ret = new PSAMDeviceAPIService(context.Connection.RemoteIpAddress.ToString()).Search(appID, userID, postData);
                            break;
                       
                        default:
                            ret = BLL.BizCommon.SimpleResultHelper.SetDataExt(BLL.BizCommon.ErrorMsg.MsgInvalidMethodName);
                            break;
                    }
                }
            }
            catch (JsonException je)//捕获json序列化反序列化异常
            {
                Common.LogHelper.Error(je.TargetSite.Name, je);
                ret = BLL.BizCommon.SimpleResultHelper.SetData("", "PostData参数异常");
            }
            catch (ArgumentException ae)//捕获参数异常
            {
                Common.LogHelper.Error(ae.TargetSite.Name, ae);
                ret = BLL.BizCommon.SimpleResultHelper.SetData(BLL.BizCommon.ErrorMsg.MsgMissingParameter, ae.Message);
            }
            catch (Exception ex)//捕获所有异常
            {
                Common.LogHelper.Error(ex.TargetSite.Name, ex);
                ret = BLL.BizCommon.SimpleResultHelper.SetDataExt(BLL.BizCommon.ErrorMsg.MsgServicesError);
            }
            IsoDateTimeConverter TimeConvert = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
            string strRet = Newtonsoft.Json.JsonConvert.SerializeObject(ret, Formatting.Indented, TimeConvert);
            context.Response.WriteAsync(strRet);
            stopwatch.Stop();//停止计时器

            //日志记录
            _inParams.Add("AppID", appID);
            _inParams.Add("UserID", userID);
            _inParams.Add("MethodName", methodName);
            _inParams.Add("Sign", sign);
            _inParams.Add("Timestamp", timestamp);
            _inParams.Add("Version", version);
            _inParams.Add("PostData", postData);
            _inParams.Add("ElapsedTimes(Seconds)", stopwatch.Elapsed.TotalSeconds);
            this.LogData(_inParams, MethodBase.GetCurrentMethod().Name, ret);
            this.LogHttpRequest(context);
            //context.Response.End();
            return Task.CompletedTask;
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

       

        public static Microsoft.AspNetCore.Http.HttpContext Current
        {
            get
            {
                object factory = ServiceProvider.GetService(typeof(Microsoft.AspNetCore.Http.IHttpContextAccessor));
                Microsoft.AspNetCore.Http.HttpContext context = ((Microsoft.AspNetCore.Http.HttpContextAccessor)factory).HttpContext;
                return context;
            }
        }



        #region 日志请求

        /// <summary>
        /// 记录api接口的入参及返回结果信息
        /// </summary>
        /// <param name="_inParams"></param>
        /// <param name="_methodName"></param>
        /// <param name="_outResult"></param>
        private void LogData(Dictionary<string, object> _inParams, string _methodName, SimpleResult _outResult)
        {
            StringBuilder logStr = new StringBuilder();

            logStr.Append(System.Environment.NewLine + _methodName);
            if (_inParams != null)
            {
                foreach (var item in _inParams)
                {
                    logStr.Append(System.Environment.NewLine + item.Key + ":" + item.Value);
                }
            }
            logStr.Append(System.Environment.NewLine + "ReturnResult");
            logStr.Append(System.Environment.NewLine + Newtonsoft.Json.JsonConvert.SerializeObject(_outResult));
            logStr.Append(System.Environment.NewLine + "-------------------------------------------------------------------------------------" + System.Environment.NewLine);
            Common.LogHelper.Info(logStr.ToString());

            _inParams.Add("ReturnResult", Newtonsoft.Json.JsonConvert.SerializeObject(_outResult));
        }

        /// <summary>
        /// 记录调用api接口的连接信息
        /// </summary>
        /// <param name="content"></param>
        private void LogHttpRequest(HttpContext content)
        {
            StringBuilder logStr = new StringBuilder();
            logStr.Append(System.Environment.NewLine + "URL");
            logStr.Append(System.Environment.NewLine + content.Request.GetDisplayUrl().ToString());
            if (content.Request.HasFormContentType)
            {
                logStr.Append(System.Environment.NewLine + "Form-Data");
                logStr.Append(System.Environment.NewLine + content.Request.Form);
                logStr.Append(System.Environment.NewLine + "-------------------------------------------------------------------------------------" + System.Environment.NewLine);
            }
            else
            {
                logStr.Append(System.Environment.NewLine + "ContentType "+ content.Request.ContentType);
            }
            if (content.Request.QueryString.HasValue)
            {
                logStr.Append(System.Environment.NewLine + "QueryString " + content.Request.QueryString.Value);
            }
            Common.LogHelper.Debug(logStr.ToString());
        }

        #endregion 日志请求
    }



    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class BussinessRequestExtensions
    {
        public static IApplicationBuilder UseBussinessRequestMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<WebAPIWork>();
        }
    }
}
